package com.keruyun.portal.whitelist.gateway.lb;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.netflix.ribbon.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * Description: com.keruyun.portal.whitelist.gateway.lb
 * </p>
 * date：2018/7/5
 * email:crowhyc@163.com
 *
 * @author Dean.Hwang
 */
public class PortalVersionLoadBalancer extends RibbonLoadBalancerClient {
    private SpringClientFactory springClientFactory;
    private PortalRoundRobinRule portalRoundRobinRule;

    public PortalVersionLoadBalancer(SpringClientFactory clientFactory, PortalRoundRobinRule portalRoundRobinRule) {
        super(clientFactory);
        this.springClientFactory = clientFactory;
        this.portalRoundRobinRule = portalRoundRobinRule;
    }

    public ServiceInstance choose(String serviceId, String version) {
        Server server = getServer(getLoadBalancer(serviceId), serviceId, version );
        if (server == null) {
            return null;
        }
        return new RibbonServer(serviceId, server, isSecure(server, serviceId),
                serverIntrospector(serviceId).getMetadata(server));
    }

    // 可能导致了 gateway 本身的谓语系统被破坏了
    protected Server getServer(ILoadBalancer loadBalancer, String serviceId, String version) {//TODO 强化版本路由
        final List<Server> allServers = loadBalancer.getReachableServers().parallelStream().filter(
                server ->
                        ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata().get("version").equalsIgnoreCase(version)

        ).collect(Collectors.toList());
        return portalRoundRobinRule.choose(allServers);

    }


    private boolean isSecure(Server server, String serviceId) {
        IClientConfig config = springClientFactory.getClientConfig(serviceId);
        ServerIntrospector serverIntrospector = serverIntrospector(serviceId);
        return RibbonUtils.isSecure(config, serverIntrospector, server);
    }

    private ServerIntrospector serverIntrospector(String serviceId) {
        ServerIntrospector serverIntrospector = springClientFactory.getInstance(serviceId,
                ServerIntrospector.class);
        if (serverIntrospector == null) {
            serverIntrospector = new DefaultServerIntrospector();
        }
        return serverIntrospector;
    }
}
